package com.wr.handler;

import com.wr.service.com.wr.request.RpcRequest;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.springframework.beans.BeansException;
import org.springframework.cglib.reflect.FastClass;
import org.springframework.cglib.reflect.FastMethod;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author 王瑞
 * @description: TODO
 * @date 2020/3/20  22:55
 * 实现ApplicationContextAware 可以获取ApplicationContext
 */
@Component
public class UserServerHandler extends ChannelInboundHandlerAdapter implements ApplicationContextAware {

    private static ApplicationContext applicationContext2;

    /*channelRead方法 负责处理请求并返回响应   ctx负责响应   msg是接收的数据*/
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //msg参数就是客户端发起调用请求是传递过来的信息 我们可以利用它来判断调用的合法性等验证

        System.out.println(msg);
        RpcRequest rpcRequest = (RpcRequest) msg;

        System.out.println("接收到请求...");
        Object proxy = createProxyInvoke(rpcRequest);
        ctx.writeAndFlush("success");   //响应数据信息给client端

    }


    /*获取ApplicationContext*/
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        applicationContext2 = applicationContext;
    }

    /*利用反射和动态代理 完成方法调用*/
    public Object createProxyInvoke(RpcRequest rpcRequest) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        String className = rpcRequest.getClassName();
        Class<?> aClass = Class.forName(className);

        Object bean = applicationContext2.getBean(aClass);

        Class<?> aClass1 = bean.getClass();
        FastClass fastClass = FastClass.create(aClass1);
        FastMethod method1 = fastClass.getMethod(rpcRequest.getMethodName(), rpcRequest.getParameterTypes());
        Object invoke = method1.invoke(bean, rpcRequest.getParameters());
        return invoke;
    }

}
